/*
 * @(#)Grap.java 1.50 04/04/14
 * 
 * Clase Compartida
 * PROP Grupo 13 Cluster 3
 */

/**
 * Esta clase implementa una estructura de datos pensada que representa un conjunto de node
 * a partir de los se va a generar un grafo a optimizar.
 * 
 * @author David Molins Goma
 */

package dominio;

import java.util.ArrayList;
import java.util.Calendar;

public class Graph {

	/*
	 * IMPORTANT
	 * Hauria de ser semblant a la de nodes, sols que aqui nomes estan les "tareas" que l'usuari hagi seleccionat per "el dia".
	 * I hauria de ser cridada pel CtrlDomino, fent que se li retorni el cami mes curt i tal. Ho dic perque no se si hauria de ser un "ArrayList<Node, Integer"
	 * o hauria de seguir sent un arraylist com a nodes. 
	 * Ja me'n diras que en penses!
	 */

	public Integer id;
	public String name;
	public String description;
	public ArrayList <Nodes> list;
	public Integer cost;
	public Calendar date;
	


	public Graph(){}

	//Creadoras
	public Graph (Integer id){
		this.id = id;
	}

	public Graph (ArrayList<Nodes> ListTarea) {
		list = ListTarea;
	}

	public Graph (Integer id, String name, String description, ArrayList<Nodes> list){
		this.id = id;
		this.name = name;
		this.description = description;
		this.list = list;
		this.cost = CalculateCost();
		this.date = Calendar.getInstance();
	}
	
	public Graph (String name, String description, ArrayList<Nodes> list){
		this.id = 0; //dudas
		this.name = name;
		this.description = description;
		this.list = list;
		this.cost = CalculateCost();
		this.date = Calendar.getInstance();
	}
	
	public Graph (Integer id, String name, String description){
		this.id = id;
		this.name = name;
		this.description = description;
		this.cost = CalculateCost();
		this.date = Calendar.getInstance();
	}


	public Graph(Graph g) { //JG
		id = g.id;
		name=g.name;
		description=g.description;
		list=g.list;
		cost=g.cost;
		date=g.date;
		
	}

	//Setters
	public void SetName (String NewName){
		this.name = NewName;
	}

	public void SetDescription (String NewDescription){
		this.description = NewDescription;
	}

	public void SetCost (Integer cost){
		this.cost = -cost;
	}

	public void SetDate (Calendar NewDate){
		this.date = NewDate;
	}
	
	public void SetList(ArrayList<Nodes> list){
		this.list = list;
	}

	//Getters
	public Integer GetId(){
		return this.id;
	}

	public String GetName(){
		return this.name;
	}

	public String GetDescription(){
		return description;
	}
	
	public Integer GetCost(){
		return this.cost;
	}

	public ArrayList<Nodes> GetList(){
		return this.list;
	}

	/*public Boolean ExistInList(Integer id){ // devuelve si el node implicito tiene arista con el del id pasado como parametro
		Boolean returnable;
		if(!this.list.isEmpty() && this.list.containsKey(id)){
				returnable = true;
		}
		else returnable = false;
		return returnable;
	}*/

	public Integer GetNumberNodes(){ // retorna el tamano del list
		return this.list.size();
	}

	public Calendar GetDate(){
		return this.date;
	}

	public void PrintGraph(){ //imprime por consola los campos del parametro implicito
		System.out.println("id: "+this.id+"\n");
		System.out.println("name: "+this.name+"\n");
		System.out.println("description: "+this.description+"\n");
		System.out.println("nodelist: ");
		for(Integer i = 0; i < list.size(); i++){
			list.get(i).PrintNodes();
		}
		System.out.println("\n");
		System.out.println("cost: "+this.cost+"\n");
	}


    private boolean NeedToPrecalculateCosts(){
        boolean needToPrecalculate = false;

        for(Nodes task : this.list){
            if(task.GetCosts() == null || task.GetCosts().size() == 0){
                needToPrecalculate = true;
                break;
            }
        }
        return needToPrecalculate;
    }

    public Integer CalculateCost(){ //retorna la suma de todos los costes totales
        //pre-calculo los costos de salto si todavia no los tengo
        if(NeedToPrecalculateCosts()) SwitchCostsCalculator.CalculateCosts(this.list);

        ArrayList<Integer> tour = OptimizationAlgorithm.DefaultTour(this.list.size());
        this.SetCost(HillClimbFitnessCalculator.Calculate(tour, this.list));
        return cost;
    }


}
